import {
    request,
    summary,
    body,
    description,
    tagsAll,
    prefix,
    responsesAll
} from 'koa-swagger-decorator-fork';

import config from 'config'
import Users from '../../controller/users'
import crypto from '../../utils/crypto'
import jwt from 'jsonwebtoken'
import sms from '../../utils/sms'

const ClientKey = config.get('clientKey')
const ExpiresIn = config.has('expiresIn')?config.get('expiresIn'):604800
const shareFolder = config.get('nextcloud.share_path')

const PhoneSchema = {
    phone: { type: 'string', required: true, example:'13333333333' }
}
const PasswdSchema = {
    passwd: { type: 'string', required: true, example:'U2FsdGVkX19R7Upm0kJ6Wf2TFSetz6wnDvY6Vvg9Cfw=' }
}
const SmsCodeSchema = {
    code:{ type: 'string', required: true,example:'1234' }
}
const ExpiresInSchema = {
    expiresIn:{
        "type": "number", example:604800
    }
}
const UserSchema = {...PhoneSchema,...PasswdSchema,...ExpiresInSchema}
const UserAttributeSchema = {
    "email": { type: 'string'},
    "organization": { type: 'string'},
    "displayname": { type: 'string'},
    "title": { type: 'string'},
    "settings": { type: 'string'}
}
const UserRegisterSchema = {...UserSchema,...SmsCodeSchema,...UserAttributeSchema}


@tagsAll(['User'])
@prefix('/users')
@responsesAll({
    200: { description: '请求成功' },
    401: {description: '请求失败(失败原因参考Response body的错误描述)'},
    500: { description: '服务器内部错误' }
})
export default class UserRouter {

    @request('POST', '/smscode')
    @summary('generate sms code')
    @description('生成手机验证码')
    @body(PhoneSchema)
    static async smscode(ctx) {
        let {phone} = ctx.request.body
        let code = await sms.generateCode(phone)
        ctx.body = process.env.NODE_ENV=='development'?{phone,code}:{}
    }

    @request('POST', '/register')
    @summary('user register')
    @description('用户注册(密码需AES加密传输)')
    @body(UserRegisterSchema)
    static async register(ctx) {
        let user= ctx.request.body,{phone,code,passwd,expiresIn} = user,exist,cache,error = new Error();
        error.status = 401;
        exist = await Users.exist(phone)
        if(exist){
            error.message = `用户${phone}已注册`
            ctx.throw(error)
        }
        cache = await sms.getCache(phone,code)
        if(!cache) {
            error.message = `用户${phone}的验证码${code}不存在或已过期`
            ctx.throw(error)
        }
        user.passwd = crypto.decryptClient(passwd)
        await Users.register(user)
        user.id = user.id||user.phone
        expiresIn = expiresIn || ExpiresIn
        let token = jwt.sign(user, ClientKey,{expiresIn});
        ctx.cookies.set('token',token)
        ctx.body = {token,shareLink:user.shareLink}
    }

    @request('DELETE', '/deregister')
    @summary('deregister user')
    @description('用户注销')
    static async deleteUser(ctx) {
        await Users.deleteUser(ctx.user.id)
        ctx.body = {}
    }

    @request('POST', '/login')
    @summary('user login')
    @description('用户登录(密码需AES加密传输)')
    @body(UserSchema)
    static async login(ctx) {
        let {phone,passwd,expiresIn} = ctx.request.body,result,user,error = new Error();
        error.status = 401
        user = await Users.exist(phone)
        if(!user){
            error.message = `用户${phone}不存在`
            ctx.throw(error)
        }
        passwd = crypto.decryptClient(passwd)
        user = {id:phone,phone,passwd}
        try{
            result = await Users.getShareByPath(user,shareFolder)
            user.shareLink = result&&result.url
        }catch(err){
            error.message = `用户${phone}密码不匹配`
            ctx.throw(error)
        }
        expiresIn = expiresIn || ExpiresIn
        user.id = user.id||user.phone
        let token = jwt.sign(user, ClientKey, {expiresIn});
        ctx.cookies.set('token',token)
        ctx.body = {token,shareLink:user.shareLink}
    }

    @request('POST', '/resetpasswd')
    @summary('reset passwd')
    @description('重置密码(密码需AES加密传输)')
    @body(UserRegisterSchema)
    static async resetPasswd(ctx) {
        let {phone,code,passwd,expiresIn} = ctx.request.body,user,result,error = new Error();
        user = await Users.exist(phone)
        if(!user){
            error.message = `用户${phone}不存在`
            ctx.throw(error)
        }
        user = await sms.getCache(phone,code)
        if(!user) {
            error.message = `用户${phone}的验证码${code}不存在或已过期`
            ctx.throw(error)
        }
        passwd = crypto.decryptClient(passwd)
        user = {id:phone,phone,passwd}
        await Users.resetUserPasswd(user.id,passwd)
        result = await Users.getShareByPath(user,shareFolder)
        user.shareLink = result&&result.url
        expiresIn = expiresIn || ExpiresIn
        user.id = user.id||user.phone
        let token = jwt.sign(user, ClientKey, {expiresIn});
        ctx.cookies.set('token',token)
        ctx.body = {token,shareLink:user.shareLink}
    }

    @request('GET', '/info')
    @summary('get user info')
    @description('获取用户属性')
    static async getUser(ctx) {
        let user = {...ctx.user}
        user = await Users.getUser(user)
        ctx.body = user
    }


    @request('PUT', '/info')
    @summary('edit user info')
    @description('编辑用户属性')
    @body(UserAttributeSchema)
    static async editUser(ctx) {
        let user = {...ctx.user,...ctx.request.body}
        await Users.editUser(user)
        ctx.body = {}
    }
}
